/* Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

import {IElement} from "./IElement";
import {IXMLDocument} from "./IXMLDocument";

/*exported JSJaCBuilder */

/**
 * This code is taken from 
 * {@link http://wiki.script.aculo.us/scriptaculous/show/Builder | script.aculo.us' Dom Builder} 
 * and has been modified to suit our
 * needs.<br/>
 * The original parts of the code do have the following
 * copyright and license notice:<br/>
 * Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us,
 * http://mir.acu lo.us) <br/>
 * script.aculo.us is freely distributable under the terms of an
 * MIT-style license.<br>
 * For details, see the script.aculo.us web site at
 * {@link http://script.aculo.us/}
 * @namespace
 */
export class  JSJaCBuilder {
    /**
     * build a new node within an xml document
     * @param {XMLDocument} doc an xml document to build the new nodes for
     * @param {string} elementName the name of the element to be created
     */
  static buildNode(doc:IXMLDocument, elementName:string,childrenOrAttribute:any,childrens:any,ns?:string):IElement {

    let element:IElement;
    // attributes (or text)
    if(childrenOrAttribute)
      if(this._isStringOrNumber(childrenOrAttribute) ||
         (childrenOrAttribute instanceof Array)) {
           let children1:any=childrenOrAttribute
        element = this._createElement(doc, elementName, ns);
        this._children(doc, element, children1);
      } else {
        let attribute1:any=childrenOrAttribute
        ns = attribute1['xmlns'] || ns;
        element = this._createElement(doc, elementName, ns);
        for(var attr in attribute1) {
          if (attribute1.hasOwnProperty(attr) && attr != 'xmlns')
            element.setAttribute(attr, attribute1[attr]);
        }
      }
    else
      element = this._createElement(doc, elementName, ns);
    // text, or array of children
    if(childrens)
      this._children(doc, element, childrens, ns);

    return element;
  }
  /**
   * @private
   */
  private static  _createElement (doc:IXMLDocument, elementName:string, ns?:string) {
    try {
      if (ns)
         return doc.createElementNS(ns, elementName);
    } catch (ex) { }

    var el = doc.createElement(elementName);

    if (ns)
      el.setAttribute("xmlns", ns);

    return el;
  }


  /**
   * 
   */
  private static _children(doc:IXMLDocument, element:IElement, children:any, ns?:string) {
    if(typeof children=='object') { // array can hold nodes and text
      for (let i in children) {
        if (children.hasOwnProperty(i)) {
          let e = children[i];
          if (typeof e=='object') {
            if (e instanceof Array) {
              var node = this.buildNode(doc, e[0], e[1], e[2], ns);
              element.appendChild(node);
            } else {
              element.appendChild(e);
            }
          } else {
            if(this._isStringOrNumber(e)) {
              element.changeOrAddNodeValue(children)
            }
          }
        }
      }
    } else {
      if(this._isStringOrNumber(children)) {
        element.changeOrAddNodeValue(children)
      }
    }
  }

  /**
   * 判断是否是字符串或者是数字
   */
  private static _isStringOrNumber(paramObject:any):boolean {
    return(typeof paramObject=='string' || typeof paramObject=='number');
  }

}
